/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package logic.business;

import data.EntityContainer;
import data.model.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import logic.business.exceptions.ConstraintException;
import logic.business.exceptions.MalformedDataException;
import logic.business.exceptions.RemoveException;
import logic.optimization.Optimizer;

/**
 *
 * @author Zenit
 */
public class DataEditor {

    private EntityContainer entityContainer;

    public DataEditor(EntityContainer entityContainer) {
        this.entityContainer = entityContainer;
    }

    public void addAirline(String id, String name, String rating, String country) throws MalformedDataException {

        Airline airline = getAirline(id, name);
        if (airline == null) {
            airline = new Airline();
            airline.setId(id);
            airline.setName(name);
            Double doubleRating = Double.parseDouble(rating);
            airline.setAirplanes(new ArrayList<Airplane>());
            airline.setCountry(country);
            airline.setRating(doubleRating.doubleValue());
            entityContainer.getAirlines().add(airline);
        } else {
            airline.setName(name);
            Double doubleRating = Double.parseDouble(rating);
            airline.setAirplanes(new ArrayList<Airplane>());
            airline.setCountry(country);
            airline.setRating(doubleRating.doubleValue());
        }

    }

    public void addAirplaneToAirline(String airlineId, String id, String model, String seats, String avgConsumption, String maxConsumption,
            String minConsumption, String capacity) throws MalformedDataException {

        Airplane airplane = getAirplane(id, model);
        Airline airline = getAirline(airlineId, "");
        if (airplane == null) {
            airplane = new Airplane();
            airplane.setId(id);
            airplane.setModel(model);
            System.out.println(capacity);
            airplane.setCapacity(Integer.parseInt(capacity));
            airplane.setSeats(Integer.parseInt(seats));
            airplane.setAvgConsumption(Integer.parseInt(avgConsumption));
            airplane.setMinConsumption(Integer.parseInt(minConsumption));
            airplane.setMaxConsumption(Integer.parseInt(maxConsumption));
            airplane.setCapacity(Integer.parseInt(capacity));
            entityContainer.getAirplanes().add(airplane);
            airline.getAirplanes().add(airplane);
        } else {
            airline.getAirplanes().add(airplane);
        }
    }
    
    public void addNewAirplane(String id, String model, String seats, String avgConsumption, String maxConsumption,
            String minConsumption, String capacity) throws MalformedDataException {

        Airplane airplane = getAirplane(id, model);
        if (airplane == null) {
            airplane = new Airplane();
            airplane.setId(id);
            airplane.setModel(model);
            System.out.println(capacity);
            airplane.setCapacity(Integer.parseInt(capacity));
            airplane.setSeats(Integer.parseInt(seats));
            airplane.setAvgConsumption(Integer.parseInt(avgConsumption));
            airplane.setMinConsumption(Integer.parseInt(minConsumption));
            airplane.setMaxConsumption(Integer.parseInt(maxConsumption));
            airplane.setCapacity(Integer.parseInt(capacity));
            entityContainer.getAirplanes().add(airplane);
        } 
    }

    public void addNewAirportToPlace(String placeName, String id, String name, int annual_number_of_passengers) throws MalformedDataException {
        Airport airport = getAirport(id, "");
        if (airport == null) {
            airport = new Airport();
            airport.setId(id);
            entityContainer.getAirports().add(airport);
        }
        airport.setName(name);
        airport.setTaxes(0);
        System.out.println(placeName);
        Place place = getPlace("",placeName);
        airport.setPlace(place);
        airport.setAnnual_number_of_passengers(annual_number_of_passengers);
    }

    public void addNewPlace(String id, String name, String importance, String population) throws MalformedDataException {
        if (id.isEmpty() || name.isEmpty() || importance.isEmpty() || population.isEmpty()) {
            throw new MalformedDataException("Not enough information to add new place");
        } else {
            Place place = getPlace(id, name);
            if (place == null) {
                place = new Place();
                place.setId(id);
                entityContainer.getPlaces().add(place);
            }
            place.setName(name);
            place.setImportance(Integer.parseInt(importance));
            place.setPopulation(Integer.parseInt(population));

        }
    }

    public void addNewRoute(String id, String frequency, String rating, String weeklyPassengers,
            String departureAirportId, String arrivalAirportId) throws MalformedDataException, ConstraintException {
        Airport dAirport = getAirport(departureAirportId, "");
        Airport aAirport = getAirport(arrivalAirportId, "");
        if (dAirport.equals(aAirport)) {
            throw new ConstraintException("Arrival airport must be different from departure airport.");
        } else {
            Route route = getRoute(id);
            if (route == null) {
                route = new Route();
                route.setId(id);
                entityContainer.getRoutes().add(route);
            }
            route.setRating(Double.parseDouble(rating));
            route.setFrequency(Integer.parseInt(frequency));
            route.setWeeklyPassengers(Integer.parseInt(weeklyPassengers));

            route.setDepartureAirport(dAirport);
            route.setArrivalAirport(aAirport);

        }
    }
    private final String dateFormat = "dd-MM-yyyy hh:mm";

    public void addNewFlight(String id, String code, String departureTime, String arrivalTime,
            String cost, String length, String airlineId, String airplaneId, String routeId) throws ParseException, MalformedDataException {
        Flight flight = getFlight(id, code);
        if (flight == null) {
            flight.setId(id);
            entityContainer.getFlights().add(flight);
        }

        flight.setCode(code);
        flight.setDepartureTime(new SimpleDateFormat(dateFormat).parse(departureTime));
        flight.setArrivalTime(new SimpleDateFormat(dateFormat).parse(arrivalTime));
        flight.setCost(Double.parseDouble(cost));
        Airline airline = getAirline(airlineId, "");
        for (Airplane plane : airline.getAirplanes()) {
            if (plane.getId().equalsIgnoreCase(airplaneId)) {
                flight.setAirplane(plane);
                break;
            }
        }
        if (flight.getAirplane() == null) {
            throw new MalformedDataException("No airplane with such id in " + airline.getName());
        }
        Route route = getRoute(routeId);
        flight.setRoute(route);

    }

    public List<Airline> getAllAirlines() {
        return entityContainer.getAirlines();
    }

    public ArrayList<Flight> getAllFlights() {
        return (ArrayList<Flight>) entityContainer.getFlights();
    }

    public List<Airport> getAllAirports() {
        return entityContainer.getAirports();
    }

    public List<Place> getAllPlaces() {
        return entityContainer.getPlaces();
    }

    public List<Route> getAllRoutes() {
        Collections.sort(entityContainer.getRoutes());
        return entityContainer.getRoutes();
    }

    /*
     * @return Vrati optimalizovanou a serazenou mnozinu Route
     */
    public List<Route> getOptimizedRoutes() {

        List<Route> routes = entityContainer.getRoutes();
        Collections.sort(routes);

        return routes;
    }

    public void optimize() {
        Optimizer.getInstance().optimizeRoutes(entityContainer);
    }

    public List<String> info() {
        return Optimizer.getInstance().getNewRoutesInfo();
    }

    public Place getPlace(String placeId, String name) throws MalformedDataException {
        if (placeId.isEmpty() && name.isEmpty()) {
            throw new MalformedDataException("Place id and name can't be null.");
        } else {
            for (Place place : entityContainer.getPlaces()) {
                if (place.getName().equalsIgnoreCase(name) || place.getId().equalsIgnoreCase(placeId)) {
                    return place;
                }
            }
            return null;
        }
    }

    public Airport getAirport(String airportId, String name) throws MalformedDataException {
        if (airportId.isEmpty() && name.isEmpty()) {
            throw new MalformedDataException("Airport Id and name can't be null.");
        } else {
            for (Airport airport : entityContainer.getAirports()) {
                if (airport.getName().equalsIgnoreCase(name) || airport.getId().equalsIgnoreCase(airportId)) {
                    return airport;
                }
            }
            return null;
        }
    }

    public Airline getAirline(String id, String name) throws MalformedDataException {
        if (id.isEmpty() && name.isEmpty()) {
            throw new MalformedDataException("Airline id and name can't be null.");
        } else {
            List<Airline> airlines = entityContainer.getAirlines();
            for (Airline airline : airlines) {
                if (airline.getName().equalsIgnoreCase(name) || airline.getId().equalsIgnoreCase(id)) {
                    return airline;
                }
            }
            return null;
        }
    }

    public Flight getFlight(String id, String code) throws MalformedDataException {
        if (id.isEmpty() && code.isEmpty()) {
            throw new MalformedDataException("Flight id and code can't be null.");
        } else {
            List<Flight> flights = entityContainer.getFlights();
            for (Flight flight : flights) {
                if (flight.getId().equalsIgnoreCase(id) || flight.getCode().equalsIgnoreCase(code)) {
                    return flight;
                }
            }
            return null;
        }
    }

    public Airplane getAirplane(String id, String model) throws MalformedDataException {
        if (id.isEmpty() && model.isEmpty()) {
            throw new MalformedDataException("Airplane id and model can't be null.");
        } else {
            List<Airplane> airplanes = entityContainer.getAirplanes();
            for (Airplane plane : airplanes) {
                if (plane.getId().equalsIgnoreCase(id) || plane.getModel().equalsIgnoreCase(model)) {
                    return plane;
                }
            }
            return null;
        }
    }

    public Route getRoute(String id) throws MalformedDataException {
        if (id.isEmpty()) {
            throw new MalformedDataException("Route id can't be null.");
        } else {
            List<Route> airplanes = entityContainer.getRoutes();
            for (Route route : airplanes) {
                if (route.getId().equalsIgnoreCase(id)) {
                    return route;
                }
            }
            return null;
        }
    }

    public void removePlace(Place place) throws RemoveException {
        List<Airport> placeAirport = getAllAirports();
        ArrayList<String> airportIds = new ArrayList<String>();
        for (Airport airport : placeAirport) {
            if (airport.getPlace().equals(place)) {
                airportIds.add(airport.getId());
            }
        }
        if (!airportIds.isEmpty()) {
            throw new RemoveException("Cascade delete is not supported.\nThe place " + place.getName() + " has airports with following ids: " + airportIds.toString());
        }
        entityContainer.getPlaces().remove(place);
    }

    public void removeFlight(Flight flight) {
        entityContainer.getFlights().remove(flight);
    }

    public void removeAirport(Airport airport) throws RemoveException {
        List<Route> routes = getAllRoutes();
        List<String> routeIds = new ArrayList<String>();
        for (Route route : routes) {
            if (route.getArrivalAirport().equals(airport) || route.getDepartureAirport().equals(airport)) {
                routeIds.add(route.getId());
            }
        }
        if (!routeIds.isEmpty()) {
            throw new RemoveException("Cascade delete is not supported.\nThe airport " + airport.getName() + " has flights with following ids: " + routeIds);
        }
        entityContainer.getAirports().remove(airport);
    }

    public void removeAirline(Airline airline) throws RemoveException {

        List<Flight> flights = getAllFlights();
        List<String> flightIds = new ArrayList<String>();
        for (Flight flight : flights) {
            if (flight.getAirline().equals(airline)) {
                flightIds.add(flight.getId());
            }
        }
        if (!flightIds.isEmpty()) {
            throw new RemoveException("Cascade delete is not supported.\nThe airline " + airline + " has flights with following ids: " + flightIds);
        }
        entityContainer.getAirlines().remove(airline);
    }

    public void removeAirplane(Airline airline, Airplane airplane) {
        airline.getAirplanes().remove(airplane);
        entityContainer.getAirplanes().remove(airplane);
    }

    public void removeRoute(Route route) throws RemoveException {
        List<Flight> flights = getAllFlights();
        List<String> flightIds = new ArrayList<String>();
        for (Flight flight : flights) {
            if (flight.getRoute().equals(route)) {
                flightIds.add(flight.getId());
            }
        }
        if (!flightIds.isEmpty()) {
            throw new RemoveException("Cascade delete is not supported.\nThe route " + route + " has flights with following ids: " + flightIds);
        }
        entityContainer.getRoutes().remove(route);
    }
}
